﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="OrderService.cs" company="">
//   
// </copyright>
// <summary>
//   The order service.
// </summary>
// --------------------------------------------------------------------------------------------------------------------


using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using Systemathics.FrameWork.Interfaces;
using System.Linq;

namespace Systemathics.FrameWork
{
    public sealed class OrderService : IDisposable
    {
        private readonly StrategyMode Mode;
        private readonly IOrderProvider OrderProvider;
        private readonly RemotingLogClient RemoteClient;
        private readonly Dictionary<Guid, int> SuscriptionCount;
        private readonly Queue<Order> OrdersQueue; 
        private readonly Queue<OrderStatusEventArgs> StatusQueue;
        private readonly Queue<OrderExectutionEventArgs>  ExecQueue;
        private readonly BackgroundWorker FrontToBackWorker;
        private readonly SystemathicsEntities db;
        public Dictionary<Guid, OrderTracker> AllStrategiesTrackers { get; private set; }

        public event EventHandler<Order> EmitOrder;
        public event EventHandler<FireMessageEventArgs> EmitError;
        public event EventHandler<FireMessageEventArgs> EmitConnectionStatus;

        #region constructor 

        public OrderService(IOrderProvider myOrderProvider)
        {
            OrderProvider = myOrderProvider;

            AllStrategiesTrackers = new Dictionary<Guid, OrderTracker>();
            OrderProvider.EmitOrderExecution += OrderProviderEmitOrderExecution;
            
            OrderProvider.EmitError += OrderProviderEmitError;
            OrderProvider.EmitConnectionStatus += OrderProviderEmitConnectionStatus;
            RemoteClient = new RemotingLogClient();

            SuscriptionCount = new Dictionary<Guid, int>();

            OrdersQueue = new Queue<Order>();
            StatusQueue = new Queue<OrderStatusEventArgs>();
            ExecQueue = new Queue<OrderExectutionEventArgs>();

            if (OrderProvider.Name == StrategyMode.BackTest.ToString())
            {
                FrontToBackWorker = new BackgroundWorker {WorkerSupportsCancellation = true};
                FrontToBackWorker.DoWork += FrontToBackWorkerDoWork;

                db = new SystemathicsEntities(GlobalVariables.EntitiesConnectionString());
                db.AcceptAllChanges();

                OrderProvider.EmitOrderStatus += OrderProviderEmitOrderStatus;
            }
            else
            {
                Mode = StrategyMode.BackTest;
                OrderProvider.EmitOrderStatus += BackTestOrderProviderEmitOrderStatus;
            }
        }

        public Dictionary<Guid, Order> OpenOrders
        {
            set
            {
                foreach (var ot in value)
                    AllStrategiesTrackers[ot.Key] = new OrderTracker(ot.Value); 
            }
        }
        #endregion constructor

        #region private methods

        private void FrontToBackWorkerDoWork(object sender, DoWorkEventArgs e)
        {
            lock (((ICollection)OrdersQueue).SyncRoot)
            {
                for (int i = 0; i < OrdersQueue.Count; i++)
                {
                    var o = OrdersQueue.Dequeue();
                    var dbo = DBOrder.CreateDBOrder(o.SendTime,o.Id,Decimal.ToDouble(o.TargetPrice),o.TargetQuantity,o.Side.ToString(),o.Style.ToString(),o.Ext.Tif.ToString());
                    dbo.DBInstruments = db.DBInstruments.Where(y => y.ID == o.InstrumentId).FirstOrDefault();
                    dbo.DBStrategies = db.DBStrategies.Where(y => y.ID == o.StrategyId).FirstOrDefault();
                    db.AddToDBOrder(dbo);
                }
                db.SaveChanges(true);
            }
            lock (((ICollection)StatusQueue).SyncRoot)
            {
                for (int i = 0; i < StatusQueue.Count; i++)
                {
                    var o = StatusQueue.Dequeue();
                    var dbs = DBOrderStatus.CreateDBOrderStatus(Guid.NewGuid(), o.Status.ToString(), Time.Now);
                    dbs.DBOrder = db.DBOrder.Where(z => z.ID == o.OrderId).FirstOrDefault();
                    db.AddToDBOrderStatus(dbs);
                }
            }
            lock (((ICollection)ExecQueue).SyncRoot)
            {
                for (int i = 0; i < ExecQueue.Count; i++)
                {
                    var o = ExecQueue.Dequeue();
                    var dbe = DBExecutions.CreateDBExecutions(Decimal.ToDouble(o.Price), o.Quantity, Time.Now, Guid.NewGuid());
                    dbe.CounterParty = o.Counterpart; 
                    dbe.DBOrder = db.DBOrder.Where(z => z.ID == o.OrderId).FirstOrDefault();
                    db.AddToDBExecutions(dbe);
                }
            }
            db.SaveChanges(true);
        }
        private void OrderProviderEmitError(object sender, FireMessageEventArgs e)
        {
            if (EmitError != null)
                EmitError(this, e);
        }
        private void OrderProviderEmitConnectionStatus(object sender, FireMessageEventArgs e)
        {
            if (EmitConnectionStatus != null)
                EmitConnectionStatus(this, e);
        }
        private void OrderProviderEmitOrderStatus(object sender, OrderStatusEventArgs e)
        {
            var status = e.Clone() as OrderStatusEventArgs;
            Guid Id = status.OrderId;
            bool canBeCancelledNow = false;
            bool canBeModifiedNow = false;

            lock (((ICollection) AllStrategiesTrackers).SyncRoot)
            {
                switch (e.Status)
                {
                    case OrderStatus.ACK:

                        if (!AllStrategiesTrackers[Id].isOpen)
                        {
                            AllStrategiesTrackers[Id].SetisAcknoweldged(true);
                            AllStrategiesTrackers[Id].SetAckTime(Time.Now); /* TODO Incompatible with back test */
                            AllStrategiesTrackers[Id].SetPendingQty(0);
                            AllStrategiesTrackers[Id].SetPendingPrice(0);
                            AllStrategiesTrackers[Id].SetStatus(OrderStatus.ACK);
                            
                            if (status.RequestedQty != null)
                                AllStrategiesTrackers[Id].TargetQuantity = (int)status.RequestedQty;
                            if (status.RequestedPrice != null)
                                AllStrategiesTrackers[Id].TargetPrice = (Decimal)status.RequestedPrice;

                            AllStrategiesTrackers[Id].SetRemainingQty((int)status.RemainingQty);
                            
                            if (AllStrategiesTrackers[Id].MustBeCancelledOnNextStatus)
                                canBeCancelledNow = true;
                            if (AllStrategiesTrackers[Id].MustBeModifiedOnNextStatus)
                                canBeModifiedNow = true;   
                        }
                        else
                            return;

                        break;
                    case OrderStatus.ACK_CANCEL:

                        if (AllStrategiesTrackers[Id].isOpen)
                        {
                            AllStrategiesTrackers[Id].SetisCancelled(true);
                            AllStrategiesTrackers[Id].SetisCancelling(false);
                            AllStrategiesTrackers[Id].SetCancelQuantity((int) status.CanceledQty);
                            AllStrategiesTrackers[Id].SetPendingQty(0);
                            AllStrategiesTrackers[Id].SetPendingPrice(0);
                            AllStrategiesTrackers[Id].SetCancelAckTime(Time.Now); /* TODO Incompatible with back test */
                            AllStrategiesTrackers[Id].SetStatus(OrderStatus.ACK_CANCEL);
                        }
                        else
                            return;

                        break;
                    case OrderStatus.ACK_MODIFY:

                        AllStrategiesTrackers[Id].SetisModified(true);
                        AllStrategiesTrackers[Id].SetisModifying(false);
                        var tgqty = AllStrategiesTrackers[status.OrderId].TargetQuantity;
                        var pdqty = AllStrategiesTrackers[status.OrderId].PendingQuantity;
                        var pdprc = AllStrategiesTrackers[status.OrderId].PendingPrice;
                        var rmqty = AllStrategiesTrackers[Id].RemainingQuantity;

                        if (pdqty > tgqty)
                            AllStrategiesTrackers[Id].SetRemainingQty(pdqty - tgqty + rmqty);
                        else if (pdqty < tgqty)
                        {
                            if (AllStrategiesTrackers[status.OrderId].TotalExecutedQuantity >= pdqty)
                                AllStrategiesTrackers[Id].SetRemainingQty(0);
                            else if (AllStrategiesTrackers[status.OrderId].TotalExecutedQuantity < pdqty)
                                AllStrategiesTrackers[Id].SetRemainingQty(pdqty - AllStrategiesTrackers[status.OrderId].TotalExecutedQuantity);
                        }

                        AllStrategiesTrackers[Id].TargetQuantity = pdqty;
                        AllStrategiesTrackers[Id].TargetPrice = pdprc;
                        AllStrategiesTrackers[Id].SetPendingQty(0);
                        AllStrategiesTrackers[Id].SetPendingPrice(0);
                        AllStrategiesTrackers[Id].SetModifyAckTime(Time.Now); /* TODO Incompatible with back test */
                        AllStrategiesTrackers[Id].SetStatus(OrderStatus.ACK_MODIFY);
                        if (AllStrategiesTrackers[status.OrderId].MustBeCancelledOnNextStatus)
                            canBeCancelledNow = true;

                        break;
                    case OrderStatus.REJECT:

                        if (AllStrategiesTrackers[Id].isOpen)
                        {
                            AllStrategiesTrackers[Id].SetisRejected(true);
                            AllStrategiesTrackers[Id].SetRejectTime(Time.Now);
                            AllStrategiesTrackers[Id].SetRejectReason(status.Reason);
                            AllStrategiesTrackers[Id].SetStatus(OrderStatus.REJECT);
                            RemoteClient.Trace(new FireMessageEventArgs(string.Format("Order ID {0}  - Reason : {1}", status.OrderId, status.Reason), Time.Now.TimeOfDay));
                        }
                        else
                            return;

                        break;
                    case OrderStatus.REJECT_CANCEL:

                        AllStrategiesTrackers[Id].SetisCancelling(false);
                        AllStrategiesTrackers[Id].SetCancelRejectNumber();
                        AllStrategiesTrackers[Id].SetRejectReason(status.Reason);
                        AllStrategiesTrackers[Id].SetStatus(OrderStatus.REJECT_CANCEL);
                        RemoteClient.Trace(new FireMessageEventArgs(string.Format("Order ID {0} CANCEL Rejected {1} times : {2}", status.OrderId, AllStrategiesTrackers[status.OrderId].CancelRejectionNumber, status.Reason), Time.Now.TimeOfDay));
                       
                        break;
                    case OrderStatus.REJECT_MODIFY:

                        AllStrategiesTrackers[Id].SetisModifying(false);
                        AllStrategiesTrackers[Id].SetModifyRejectNumber();
                        AllStrategiesTrackers[Id].SetRejectReason(status.Reason);
                        AllStrategiesTrackers[Id].SetStatus(OrderStatus.REJECT_MODIFY);
                        RemoteClient.Trace(new FireMessageEventArgs(string.Format("Order ID {0} MODIFY Rejected {1} times : {2}", status.OrderId, AllStrategiesTrackers[status.OrderId].ModifyRejectedNumber, status.Reason), Time.Now.TimeOfDay));
                        if (AllStrategiesTrackers[Id].MustBeCancelledOnNextStatus)
                            canBeCancelledNow = true;

                        break;
                    default:
                        break;
                }

                if (canBeCancelledNow)
                {
                    if (Cancel(AllStrategiesTrackers[Id]))
                        AllStrategiesTrackers[Id].MustBeCancelledOnNextStatus = false;
                }

                if (canBeModifiedNow)
                {
                    if (Modify(AllStrategiesTrackers[Id], AllStrategiesTrackers[Id]))
                        AllStrategiesTrackers[Id].MustBeModifiedOnNextStatus = false;
                }
                StatusQueue.Enqueue(status);
            }
            EmitOrder(this, AllStrategiesTrackers[Id]);
        }
        private void BackTestOrderProviderEmitOrderStatus(object sender , OrderStatusEventArgs e)
        {
            var status = e.Clone() as OrderStatusEventArgs;
            Guid Id = status.OrderId;
            bool canBeCancelledNow = false;
            bool canBeModifiedNow = false;

            lock (((ICollection)AllStrategiesTrackers).SyncRoot)
            {
                switch (e.Status)
                {
                    case OrderStatus.ACK:

                        if (!AllStrategiesTrackers[Id].isOpen)
                        {
                            AllStrategiesTrackers[Id].SetisAcknoweldged(true);

                            AllStrategiesTrackers[Id].SetSendTime(status.SendTime); // Compatible with back test 
                            AllStrategiesTrackers[Id].SetAckTime(status.AckTime);   // Compatible with back test 
                            
                            AllStrategiesTrackers[Id].SetPendingQty(0);
                            AllStrategiesTrackers[Id].SetPendingPrice(0);
                            AllStrategiesTrackers[Id].SetStatus(OrderStatus.ACK);

                            if (status.RequestedQty != null)
                                AllStrategiesTrackers[Id].TargetQuantity = (int)status.RequestedQty;
                            if (status.RequestedPrice != null)
                                AllStrategiesTrackers[Id].TargetPrice = (Decimal)status.RequestedPrice;

                            AllStrategiesTrackers[Id].SetRemainingQty((int)status.RemainingQty);

                            if (AllStrategiesTrackers[Id].MustBeCancelledOnNextStatus)
                                canBeCancelledNow = true;
                            if (AllStrategiesTrackers[Id].MustBeModifiedOnNextStatus)
                                canBeModifiedNow = true;
                        }
                        else
                            return;

                        break;
                    case OrderStatus.ACK_CANCEL:

                        if (AllStrategiesTrackers[Id].isOpen)
                        {
                            AllStrategiesTrackers[Id].SetisCancelled(true);
                            AllStrategiesTrackers[Id].SetisCancelling(false);
                            AllStrategiesTrackers[Id].SetCancelQuantity((int)status.CanceledQty);
                            AllStrategiesTrackers[Id].SetPendingQty(0);
                            AllStrategiesTrackers[Id].SetPendingPrice(0);

                            AllStrategiesTrackers[Id].SetCancelTime(status.CancelTime);       // Compatible with back test
                            AllStrategiesTrackers[Id].SetCancelAckTime(status.CancelAckTime); // Compatible with back test
                            
                            AllStrategiesTrackers[Id].SetStatus(OrderStatus.ACK_CANCEL);
                        }
                        else
                            return;

                        break;
                    case OrderStatus.ACK_MODIFY:

                        AllStrategiesTrackers[Id].SetisModified(true);
                        AllStrategiesTrackers[Id].SetisModifying(false);
                        var tgqty = AllStrategiesTrackers[status.OrderId].TargetQuantity;
                        var pdqty = AllStrategiesTrackers[status.OrderId].PendingQuantity;
                        var pdprc = AllStrategiesTrackers[status.OrderId].PendingPrice;
                        var rmqty = AllStrategiesTrackers[Id].RemainingQuantity;

                        if (pdqty > tgqty)
                            AllStrategiesTrackers[Id].SetRemainingQty(pdqty - tgqty + rmqty);
                        else if (pdqty < tgqty)
                        {
                            if (AllStrategiesTrackers[status.OrderId].TotalExecutedQuantity >= pdqty)
                                AllStrategiesTrackers[Id].SetRemainingQty(0);
                            else if (AllStrategiesTrackers[status.OrderId].TotalExecutedQuantity < pdqty)
                                AllStrategiesTrackers[Id].SetRemainingQty(pdqty - AllStrategiesTrackers[status.OrderId].TotalExecutedQuantity);
                        }

                        AllStrategiesTrackers[Id].TargetQuantity = pdqty;
                        AllStrategiesTrackers[Id].TargetPrice = pdprc;
                        AllStrategiesTrackers[Id].SetPendingQty(0);
                        AllStrategiesTrackers[Id].SetPendingPrice(0);

                        AllStrategiesTrackers[Id].SetModifyTime(status.ModifyTime);       // Compatible with back test 
                        AllStrategiesTrackers[Id].SetModifyAckTime(status.ModifyAckTime); // Compatible with back test 
                        
                        AllStrategiesTrackers[Id].SetStatus(OrderStatus.ACK_MODIFY);
                        if (AllStrategiesTrackers[status.OrderId].MustBeCancelledOnNextStatus)
                            canBeCancelledNow = true;

                        break;
                    case OrderStatus.REJECT:

                        if (AllStrategiesTrackers[Id].isOpen)
                        {
                            AllStrategiesTrackers[Id].SetisRejected(true);

                            AllStrategiesTrackers[Id].SetRejectTime(status.RejectTime); // Compatible with back test 
                            
                            AllStrategiesTrackers[Id].SetRejectReason(status.Reason);
                            AllStrategiesTrackers[Id].SetStatus(OrderStatus.REJECT);
                            RemoteClient.Trace(new FireMessageEventArgs(string.Format("Order ID {0}  - Reason : {1}", status.OrderId, status.Reason), Time.Now.TimeOfDay));
                        }
                        else
                            return;

                        break;
                    case OrderStatus.REJECT_CANCEL:

                        AllStrategiesTrackers[Id].SetisCancelling(false);
                        AllStrategiesTrackers[Id].SetCancelRejectNumber();
                        AllStrategiesTrackers[Id].SetRejectReason(status.Reason);
                        AllStrategiesTrackers[Id].SetStatus(OrderStatus.REJECT_CANCEL);
                        RemoteClient.Trace(new FireMessageEventArgs(string.Format("Order ID {0} CANCEL Rejected {1} times : {2}", status.OrderId, AllStrategiesTrackers[status.OrderId].CancelRejectionNumber, status.Reason), Time.Now.TimeOfDay));

                        break;
                    case OrderStatus.REJECT_MODIFY:

                        AllStrategiesTrackers[Id].SetisModifying(false);
                        AllStrategiesTrackers[Id].SetModifyRejectNumber();
                        AllStrategiesTrackers[Id].SetRejectReason(status.Reason);
                        AllStrategiesTrackers[Id].SetStatus(OrderStatus.REJECT_MODIFY);
                        RemoteClient.Trace(new FireMessageEventArgs(string.Format("Order ID {0} MODIFY Rejected {1} times : {2}", status.OrderId, AllStrategiesTrackers[status.OrderId].ModifyRejectedNumber, status.Reason), Time.Now.TimeOfDay));
                        if (AllStrategiesTrackers[Id].MustBeCancelledOnNextStatus)
                            canBeCancelledNow = true;

                        break;
                    default:
                        break;
                }

                if (canBeCancelledNow)
                {
                    if (Cancel(AllStrategiesTrackers[Id]))
                        AllStrategiesTrackers[Id].MustBeCancelledOnNextStatus = false;
                }

                if (canBeModifiedNow)
                {
                    if (Modify(AllStrategiesTrackers[Id], AllStrategiesTrackers[Id]))
                        AllStrategiesTrackers[Id].MustBeModifiedOnNextStatus = false;
                }
            }
            EmitOrder(this, AllStrategiesTrackers[Id]);
        }
        private void OrderProviderEmitOrderExecution(object sender, OrderExectutionEventArgs e)
        {
            if(!AllStrategiesTrackers[e.OrderId].isOpen)
                OrderProviderEmitOrderStatus(this, new OrderStatusEventArgs(e.OrderId) { Status = OrderStatus.ACK, RemainingQty = AllStrategiesTrackers[e.OrderId].RemainingQuantity });
            
            var exec = e.Clone() as OrderExectutionEventArgs;
            lock (((ICollection) AllStrategiesTrackers).SyncRoot)
            {
                int qty = AllStrategiesTrackers[exec.OrderId].TotalExecutedQuantity + exec.Quantity;

                AllStrategiesTrackers[exec.OrderId].SetExecutedAveragePrice((AllStrategiesTrackers[exec.OrderId].ExecutedAveragePrice*AllStrategiesTrackers[exec.OrderId].TotalExecutedQuantity + exec.Price*exec.Quantity)/qty);
                AllStrategiesTrackers[exec.OrderId].SetTotalExecutedQuantity(qty);
                AllStrategiesTrackers[exec.OrderId].AddExecution(new Execution(e.OrderId, e.Price, e.Quantity, e.Counterpart));
                AllStrategiesTrackers[exec.OrderId].SetRemainingQty(AllStrategiesTrackers[exec.OrderId].TargetQuantity - AllStrategiesTrackers[exec.OrderId].TotalExecutedQuantity);

                if (AllStrategiesTrackers[exec.OrderId].RemainingQuantity != 0)
                    AllStrategiesTrackers[exec.OrderId].SetStatus(OrderStatus.PARTIALLY_FILLED);
                else
                    AllStrategiesTrackers[exec.OrderId].SetStatus(OrderStatus.FILLED);
            }

            if(Mode != StrategyMode.BackTest)
                ExecQueue.Enqueue(exec);
            
            EmitOrder(this, AllStrategiesTrackers[exec.OrderId]);

            if (OrdersQueue.Count > 3 && Mode != StrategyMode.BackTest)
            {
                if (!FrontToBackWorker.IsBusy)
                    FrontToBackWorker.RunWorkerAsync();
            }
        }

        #endregion private methods

        #region Public methods 

        public string Name
        {
            get { return OrderProvider.Name; }
        }
        public bool isConnected
        {
            get { return OrderProvider.isConnected; }
        }
        public void Connect()
        {
            OrderProvider.Connect();
        }
        public void Disconnect()
        {
            OrderProvider.Disconnect();
        }
        public void Suscribe(Instrument instrument)
        {
            OrderProvider.Suscribe(instrument);

            if (!SuscriptionCount.ContainsKey(instrument.Id))
                SuscriptionCount.Add(instrument.Id, 0);

            SuscriptionCount[instrument.Id]++;
        }
        public void Unsubscribe(Instrument instrument)
        {
            if (SuscriptionCount[instrument.Id] == 1)
                OrderProvider.Unsubscribe(instrument);

            SuscriptionCount[instrument.Id]--;
        }
        public bool Send(Order o)
        {
            lock (AllStrategiesTrackers)
            {
                AllStrategiesTrackers[o.Id] = new OrderTracker(o);


                if (Mode != StrategyMode.BackTest)
                {
                    AllStrategiesTrackers[o.Id].SetSendTime(Time.Now);
                    OrdersQueue.Enqueue(o);
                }
                
                AllStrategiesTrackers[o.Id].SetRemainingQty(o.TargetQuantity);
                AllStrategiesTrackers[o.Id].SetPendingQty(o.TargetQuantity);
                AllStrategiesTrackers[o.Id].SetPendingPrice(o.TargetPrice);

                AllStrategiesTrackers[o.Id].SetisSent(OrderProvider.Send(AllStrategiesTrackers[o.Id]));
                if (!AllStrategiesTrackers[o.Id].isSent)
                {
                    AllStrategiesTrackers[o.Id].SetPendingQty(0);
                    AllStrategiesTrackers[o.Id].SetPendingPrice(0);
                }
                return AllStrategiesTrackers[o.Id].isSent;
            }
        }
        public bool Cancel(Order o)
        {
            // What's about Modifying orders that we cannot cancel because we wait ACK_MODIFY before to cancel it !
            // What' about alive orders which are taken into account by market with an ACK just after a CancellAll Action ????
            // sinon, y'a une autre methode pour resoudre ce probleme, c'est de rajouter dans OrderCell un autre champs (NextStatus) 
            // là tu peux faire un cancel sur un ordre pending par exemple 
            // j'ai pensé à ça, mais je voulais pas trop compliquer les ordres pour des cas tres rares ! 
            // par exemple, qd tu fais Cancel alors que ton Ordre est isModifying, tu mets nextStatus=Cancel, et qd tu recois un ackmodif ou rejmodif, 
            // tu renvois un CancelOrder 

            lock (AllStrategiesTrackers)
            {
                if (AllStrategiesTrackers.ContainsKey(o.Id))
                {
                    if (AllStrategiesTrackers[o.Id].isOpen && !AllStrategiesTrackers[o.Id].isModifying &&
                        !AllStrategiesTrackers[o.Id].isCancelling)
                    {
                        AllStrategiesTrackers[o.Id].SetPendingQty(o.RemainingQuantity);
                        AllStrategiesTrackers[o.Id].SetPendingPrice(o.TargetPrice);

                        if (Mode != StrategyMode.BackTest)
                            AllStrategiesTrackers[o.Id].SetCancelTime(Time.Now);
                        
                        AllStrategiesTrackers[o.Id].SetisCancelling(OrderProvider.Cancel(AllStrategiesTrackers[o.Id]));
                        return AllStrategiesTrackers[o.Id].isCancelling;
                    }

                    if (AllStrategiesTrackers[o.Id].isPending && !AllStrategiesTrackers[o.Id].isCancelling)
                        // can cancel an order which is beeing modifying
                        AllStrategiesTrackers[o.Id].MustBeCancelledOnNextStatus = true;
                }
                return false;
            }
        }
        public bool Modify(Order oldo, Order newo)
        {
            lock (AllStrategiesTrackers)
            {
                if (AllStrategiesTrackers.ContainsKey(oldo.Id))
                {
                    if (AllStrategiesTrackers[oldo.Id].isOpen && !AllStrategiesTrackers[oldo.Id].isModifying &&
                        !AllStrategiesTrackers[oldo.Id].isCancelling)
                    {
                        // SetRemainingQty ??? will be given by the market in the call back any way ...
                        // Dont set remaining here with pendings - remainings etc ...because the modification could give reject modify, better to let it given by the market in thr call back
                        // idee here: Pending Qts , prices represent what must be modified, remember pendings value now are public, set up upper.
                        AllStrategiesTrackers[oldo.Id].SetPendingQty(newo.TargetQuantity);
                        AllStrategiesTrackers[oldo.Id].SetPendingPrice(newo.TargetPrice);

                        if (Mode != StrategyMode.BackTest)
                            AllStrategiesTrackers[oldo.Id].SetModifyTime(Time.Now);

                        AllStrategiesTrackers[oldo.Id].SetisModifying(
                            OrderProvider.Modify(AllStrategiesTrackers[oldo.Id]));
                        if (!AllStrategiesTrackers[oldo.Id].isModifying)
                        {
                            AllStrategiesTrackers[oldo.Id].SetPendingQty(0);
                            AllStrategiesTrackers[oldo.Id].SetPendingPrice(0);
                        }

                        return AllStrategiesTrackers[oldo.Id].isModifying;
                    }

                    if (AllStrategiesTrackers[oldo.Id].isPending && !AllStrategiesTrackers[oldo.Id].isModifying &&
                        !AllStrategiesTrackers[oldo.Id].isCancelling)
                        AllStrategiesTrackers[oldo.Id].MustBeModifiedOnNextStatus = true;
                }

                return false;
            }
        }
        public int CancelAllStrategiesOrders()
        {
            int n = 0;
            lock (AllStrategiesTrackers)
            {
                foreach (OrderTracker o in AllStrategiesTrackers.Values)
                    n += Cancel(o) ? 1 : 0;
            }

            return n;
        }
        public int CancelAllStrategiesBuyOrders()
        {
            int n = 0;
            lock (AllStrategiesTrackers)
            {
                foreach (OrderTracker o in AllStrategiesTrackers.Values)
                {
                    if (o.Side == OrderSide.Buy)
                        n += Cancel(o) ? 1 : 0;
                }
            }

            return n;
        }
        public int CancelAllStrategiesSellOrders()
        {
            int n = 0;
            lock (AllStrategiesTrackers)
            {
                foreach (OrderTracker o in AllStrategiesTrackers.Values)
                {
                    if (o.Side == OrderSide.Sell)
                        n += Cancel(o) ? 1 : 0;
                }
            }

            return n;
        }

        #endregion Public methods

        #region IDisposable Members

        public void Dispose()
        {
            OrderProvider.EmitOrderExecution -= OrderProviderEmitOrderExecution;
            OrderProvider.EmitOrderStatus -= OrderProviderEmitOrderStatus;
            OrderProvider.EmitError -= OrderProviderEmitError;
            OrderProvider.EmitConnectionStatus -= OrderProviderEmitConnectionStatus;

            if(Mode != StrategyMode.BackTest)
                FrontToBackWorker.RunWorkerAsync();
                //FrontToBackWorker.DoWork -= FrontToBackWorkerDoWork;
                //FrontToBackWorker.Dispose();
                //db.Dispose();
        }

        #endregion
    }
}